//
// File  : CustomerProfile.cpp
// Team  : Dangling Pointers
// Class : CST 236 - Software Testing
//
// CustomerProfile definitions.
//

#include "CustomerProfileController.h"
#include "Global.h"
#include <iostream>


// constructor
CustomerProfileController::CustomerProfileController(CustomerDatabase* customerdatabase) 
	: m_customerdatabase(customerdatabase)
{
	displayMenu();
}

//
// displayMenu : void
//
// method will display the menu for the CustomerProfile and then prompt for user
// input corresponding to menu choice.
//
void CustomerProfileController::displayMenu()
{
	while (true) 
	{
		clearConsole();

		std::string menuName = "Customer Profile";
		std::cout << std::endl << "====== " << menuName << " ======" << std::endl;
		std::cout << "1. View Customer Profile." << std::endl;
		std::cout << "2. Edit Customer Profile." << std::endl;
		std::cout << "3. Create Customer Profile." << std::endl;
		std::cout << "4. Main Menu." << std::endl;

		int input = getUserInput(4);

		switch(input)
		{
		case 1:
			clearConsole();
			viewProfile();
			pressEnterToContinue();
			break;

		case 2:
			clearConsole();
			editProfile();
			pressEnterToContinue();
			break;

		case 3:
			clearConsole();
			createProfile();
			pressEnterToContinue();
			break;

		default:
			return;
		}
	}
}

//
// viewProfile : void
//
// method will display relevant CustomerProfile info given a name
// 
//
void CustomerProfileController::viewProfile() const
{
	bool customerFound = true;
	std::string name;

	while (true) 
	{
		std::cout << "Enter name of profile you wish to view: ";
		getline(std::cin, name);

		if (name.size() == 0) 
			return;

		try 
		{
			clearConsole();

			std::cout << std::endl << "======" << "User Profile" << "======" << std::endl;
			std::cout << "Name: " << m_customerdatabase->getCustomer(name).getName() << std::endl;
			std::cout << "Phone Number: " << m_customerdatabase->getCustomer(name).getPhoneNumber() << std::endl;
			std::cout << "Email: " << m_customerdatabase->getCustomer(name).getEmail() << std::endl;
			std::cout << std::endl;

			customerFound = true;
		} 
		catch (std::exception) 
		{
			customerFound = false;
		}

		if (customerFound) 
			break;

		std::cout << "User not found! ";
	}
}

//
// editProfile : void
//
// method will allow you to edit a CustomerProfile given a name
// 
//
void CustomerProfileController::editProfile()
{
	bool customerFound = true;
	std::string name;

	while (true) 
	{
		std::cout << "Enter name of profile you wish to edit (or nothing to cancel): ";
		getline(std::cin, name);

		if (name.size() == 0) 
			return;

		try 
		{
			clearConsole();

			// check to see that record exists.
			m_customerdatabase->getCustomer(name).getName();
			customerFound = true;

		} 
		catch (std::exception) 
		{
			customerFound = false;
		}

		if (customerFound)
		{
			// Prompts user for edit menu
			promptEdit(name);
			break;
		}

		std::cout << "User not found! " << std::endl;
	}
}

//
// createProfile : void
//
// method will allow user to create a CustomerProfile
// prompts user to enter Name, Phone #, and Email
//
void CustomerProfileController::createProfile()
{
	bool validEntry = true;

	std::string key;
	std::string phone;
	std::string email;

	// 1st - prompt user for name, this becomes the key
	while (true) 
	{
		bool customerFound = true;

		std::cout << "Enter your name: ";
		getline(std::cin, key);

		// if the user entered nothing, go back to menu
		if (key.size() == 0) 
			return;

		// ensure that the customer is not already in the database
		try 
		{
			m_customerdatabase->getCustomer(key).getName();
			customerFound = true;

		} 
		catch (std::exception) 
		{
			customerFound = false;
		}

		if(customerFound)
		{
			std::cout << "Customer already exists!" << std::endl;
			continue;
		}

		break;
	}

	// 2nd - prompt for phone number
	while (true)
	{
		std::cout << "Enter your phone (format: XXX-XXX-XXXX): ";
		getline(std::cin, phone);

		// if the user entered nothing, go back to menu
		if (phone.size() == 0)
			return;

		//
		// if the phone number doesn't match the specified format, print
		// an error message and continue with the loop.
		//
		if ( !validatePhoneNumber(phone) )
		{
			std::cout << "Invalid phone format! " << std::endl;
			continue;
		}

		break;
	}

	// 3rd - prompt for email address
	while (true)
	{
		// TODO: validate the email address
		std::cout << "Enter your email (format: name@provider.com): ";
		getline(std::cin, email);

		if (phone.size() == 0)
			return;

		if( !validateEmailAddress(email) )
		{
			std::cout << "Invalid email format! " << std::endl;
			continue;
		}

		// add the customer to the customer database
		try 
		{
			m_customerdatabase->addCustomer(key, Customer(key, phone, email));
			validEntry = true;
		} 
		catch (std::exception) 
		{
			validEntry = false;
		}

		// if the customer entry is valid, create a new profile for them
		if (validEntry)
		{
			std::cout << "Profile Created" << std::endl << std::endl;
			break;
		}

		std::cout << "Invalid Customer Entry! ";
	}
}

//
// promptEdit: void
//
// method prompts user for Profile edit, this is a sub-method contained in editProfile
// 
//
void CustomerProfileController::promptEdit(const std::string& name)
{
	while (true) 
	{
		clearConsole();

		std::string menuName = "Edit Profile";
		std::cout << std::endl << "====== " << menuName << " ======" << std::endl;
		std::cout << "1. Edit Phone." << std::endl;
		std::cout << "2. Edit Email." << std::endl;
		std::cout << "3. Main Menu." << std::endl;

		int input = getUserInput(3);

		std::string buffer = "empty";

		switch(input)
		{
		case 1:
			clearConsole();

			// keep looping if the user enters an invalid phone number
			while (true)
			{
				// Edit Phone
				std::cout << "Enter new phone (format XXX-XXX-XXXX):";
				std::getline(std::cin, buffer);

				if( !validatePhoneNumber(buffer) )
				{ 
					std::cout << "Invalid phone format!" << std::endl;
					continue;
				}

				m_customerdatabase->changeCustomerPhone(name, buffer);
				break;
			}

			return;

		case 2:
			clearConsole();

			// Edit Email
			std::cout << "Enter new email (format: name@provider.com):";
			std::getline(std::cin, buffer);

			m_customerdatabase->changeCustomerEmail(name, buffer);

			return;

		default:
			return;
		}
	}
}

//
// validatePhoneNumber : bool
// 
// Procedure will check to see if a phone number is valid or not. If it is, return
// true. Otherwise, return false.
//
bool CustomerProfileController::validatePhoneNumber(const std::string& phone)
{
	int i = 0;

	// validate phone number length
	if (phone.length() != 12)
		return false;

	// validate first three digits
	for(; i < 3; ++i)
	{
		if( !isdigit(phone[i]) )
			return false;
	}

	// validate first dash
	if ( phone[i] != '-' )
		return false;
	++i;

	// validate middle three digits
	for(; i < 7; ++i)
	{
		if ( !isdigit(phone[i]) )
			return false;
	}

	// validate second dash
	if ( phone[i] != '-' )
		return false;
	++i;

	// validate last four digits
	for(; i < 12; ++i)
	{
		if( !isdigit(phone[i]) )
			return false;
	}
	return true;
}

//
// validateEmailAddress : bool
//
// Procedure will check to see if an email address is valid or not. If it is,
// return true. Otherwise, return false.
//
bool CustomerProfileController::validateEmailAddress(const std::string& email)
{
	size_t i = 0;
	bool isValid = false;

	// ensure that email address has a "@" symbol
	for(; i < email.length(); ++i)
	{
		if ( email[i] == '@' )
		{
			isValid = true;
			++i;
			break;
		}
	}

	// ensure that "@" is not the first character in the string
	if (email[0] == '@')
		isValid = false;

	//
	// return if there was no "@" character found or if "@" character
	// was found at the beginning of the string.
	//
	if (isValid == false)
		return isValid;

	//
	// ensure that next character after "@" symbol is not a "." and that
	// the last character is also not a "."
	//
	if ( email[i] == '.' || email[ email.length()-1 ] == '.' )
		return false;

	// ensure that there is a "." somewhere in the string
	for (; i < email.length(); ++i)
	{
		if( email[i] == '.')
			return true;
	}

	return false;
}